package com.auxgroup.hr.front.site.inteceptor;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.auxgroup.hr.front.commons.utils.HttpClientUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;
import com.auxgroup.hr.front.commons.Constant;
import com.auxgroup.hr.front.commons.config.BusinessConfig;
import com.auxgroup.hr.front.commons.utils.AESUtil;
import com.auxgroup.hr.front.commons.utils.SpringUtil;
import com.auxgroup.hr.front.commons.vo.UserDTO;
import com.auxgroup.hr.front.service.comm.OprdefnService;

/**
 * @author lvliuhao
 * @version 创建时间：2018年5月23日 上午10:11:32
 * 类说明
 */
public class SecurityUserInteceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(SecurityUserInteceptor.class);

    private BusinessConfig businessConfig;
    private OprdefnService oprdefnService;

    public SecurityUserInteceptor(BusinessConfig businessConfig, OprdefnService oprdefnService) {
        this.businessConfig = businessConfig;
        this.oprdefnService = oprdefnService;
    }

    /**
     * <p>Title: afterCompletion</p>
     * <p>Description:
     * 该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行，
     * 该方法将在整个请求结束之后，也就是在DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。</p>
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response, Object arg2, Exception arg3)
            throws Exception {
    }

    /**
     * <p>Title: postHandle</p>
     * <p>Description:
     * 该方法将在请求处理之后，DispatcherServlet进行视图返回渲染之前进行调用，
     * 可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。</p>
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
                           Object arg2, ModelAndView arg3) throws Exception {
    }

    /**
     * <p>Title: preHandle</p>
     * <p>Description:
     * 该方法将在请求处理之前进行调用，只有该方法返回true，才会继续执行后续的Interceptor和Controller，
     * 当返回值为true 时就会继续调用下一个Interceptor的preHandle 方法，
     * 如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法</p>
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object arg2) throws Exception {
        String uri = request.getRequestURI();
        String oprId = request.getParameter("oprid");
        logger.info("->request uri:{},request param:{}", uri, request.getQueryString());
        HttpSession session = request.getSession();
        //不需要控制的url直接返回true
        if (uri.startsWith("/api/hr/hire")) {
            return true;
        }
        //不需要控制的url直接返回true
        if (Constant.NOT_NEED_USER_LOGIN_URI.contains(uri)) {
            return true;
        }

        //url中可直接切换用户
        if ("/index".equals(uri) && StringUtils.isNotEmpty(oprId)) {
            logger.info("url中可直接切换用户 " + oprId);
            UserDTO user = oprdefnService.getUserDto(oprId);
//			if(user!=null){
            if (user != null) {
                logger.info("登陆成功 " + user.getEmplId());
            } else {
                logger.info("登陆失败 " + oprId);
            }
            session.setAttribute("user", user);
            return true;
//			}
        }
        //本地环境单独设置
        if ("local".equals(SpringUtil.getActiveProfile())) {
            if (session.getAttribute("user") == null) {
                if (StringUtils.isEmpty(oprId)) {
                    oprId = "xiecheng";//"ibmglj";//"wl1";//"nitongqian";//"wl";//
                }
                session.setAttribute("user", oprdefnService.getUserDto(oprId));
            }
            return true;
        }
        //本地环境单独设置
//		if("uat".equals(SpringUtil.getActiveProfile())){
//			if(session.getAttribute("user")==null){
//				if(StringUtils.isEmpty(oprId)){
//					oprId = "gufan";//"wuhaiyan3";//"liufang15";//"laishengnan";//"shenguoying";//"guxunfeng";//"liangmeng";//"wulihua";//"daidongdong";//"baif";//"xiongyuze";//"wl1";//"ibmglj";//
//				}
//				session.setAttribute("user", oprdefnService.getUserDto(oprId));
//			}
//
//			return true;
//		}
        //如果存在user 则说明已登录过。直接返回
        if (session.getAttribute("user") != null) {
            return true;
        }
//		//SSO单点登录控制
//		String ticket = request.getParameter("ticket");
//		//ticket为空的时候直接去登录
//		if(StringUtils.isNotBlank(ticket)){
//			oprId = getOprid(ticket);
//			if(oprId!=null){
//				UserDTO user = oprdefnService.getUserDto(oprId);
//				if(user!=null){
//					session.setAttribute("user", user);
//					return true;
//				}
//			}
//		}
//		//url中拼接用户登录
//		String loginOprid = getLoginOpridFromRequest(request, "loginOprid");
//		if(StringUtils.isNotBlank(loginOprid)){
//			UserDTO user = oprdefnService.getUserDto(loginOprid);
//			if(user!=null){
//				session.setAttribute("user", user);
//				return true;
//			}
//			loginOprid = decodeByJsUnescape(loginOprid);
//			loginOprid = getOpridByAES(loginOprid);
//			user = oprdefnService.getUserDto(loginOprid);
//			if(user!=null){
//				session.setAttribute("user", user);
//				return true;
//			}
//		}

        //url中拼接用户登录
        String decStr = getLoginOpridFromRequest(request, "decstring");
        if (StringUtils.isNotBlank(decStr)) {
            String loginOprid = getDecOprid(decStr);
            logger.info("getDecOprid " + loginOprid);
            UserDTO user = oprdefnService.getUserDto(loginOprid);
            if (user != null) {
                session.setAttribute("user", user);
                return true;
            }
            logger.info("no user getDecOprid ");
        }
        //session失效。或者获取不到用户信息时，去登录
        if (session.getAttribute("user") == null) {
            logger.info("session is out of time");
            response.setStatus(5002);
//			response.sendRedirect(businessConfig.getCasServerUrl()+"?appurl="+businessConfig.getCasservicePath());
            return false;
        }
        return true;
    }

    private String getDecOprid(String decStr) {
        JSONObject jo = HttpClientUtil.doGet(businessConfig.getCasTokenDecUrl() + decStr);
        logger.info(jo.toString());
        if (jo == null) {
            return "";
        }

        //优先获取账号，如果账号有值则判断是钉钉打开
        Object a = jo.get("account");
        if (a != null) {
            String account = (String) a;
            if (!StringUtils.isEmpty(account)) {
                logger.info("获取员工钉钉账号信息：" + account);
                return account;
            }
        }

        return (String) jo.get("userId");
    }


    /**
     * 根据ticket 获取用户信息
     *
     * @param ticket
     * @return
     */
    private String getOprid(String ticket) {
        String orpid = null;
        try {
            URL l_url = new URL(businessConfig.getCasServerUrl() + "validate?ticket=" + ticket + "&service=" + businessConfig.getCasservicePath());
            HttpURLConnection l_connection = (java.net.HttpURLConnection) l_url.openConnection();
            l_connection.connect();
            InputStream l_urlStream = l_connection.getInputStream();
            BufferedReader l_reader = new BufferedReader(new InputStreamReader(l_urlStream));
            String isOk = l_reader.readLine();
            logger.info("validate ticket result:{}", isOk);
            if ("yes".equals(isOk.trim())) {
                orpid = l_reader.readLine().trim();
                logger.info("get oprId result:{}", orpid);
            }
        } catch (Exception e) {
            logger.error("get oprid error：", e);
            return null;
        }
        return orpid;
    }

    /**
     * 从json中获取oprid
     *
     * @param token
     * @return
     */
    private String getOpridByAES(String token) {
        String jsonStr = AESUtil.decrypt(token);
        logger.info("AES decrypt result:{}", jsonStr);
        JSONObject opridJson = JSONObject.parseObject(jsonStr);
        if (opridJson != null) {
            return opridJson.getString("userLoginName");
        }
        return null;
    }


    private String getLoginOpridFromRequest(HttpServletRequest request, String key) {
        String queryStr = request.getQueryString();
        if (StringUtils.isNotEmpty(queryStr)) {
            String[] params = queryStr.split("&");
            for (String param : params) {
                String[] keyVal = param.split("=");
                if (key.equals(keyVal[0]) && keyVal.length > 1) {
                    return keyVal[1];
                }
            }
        }
        return null;
    }

    private String decodeByJsUnescape(String token) {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByExtension("js");
        try {
            //直接解析
            Object res = engine.eval(" unescape('" + token + "')");
            return res.toString();
        } catch (Exception ex) {
            return null;
        }
    }


}
